package org.ezplatform.office.meeting.task.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.MapUtils;
import org.ezplatform.cloud.api.system.user.UserApiService;
import org.ezplatform.cloud.common.util.JwtUtils;
import org.ezplatform.core.dao.jpa.JpaBaseDao;
import org.ezplatform.core.pagination.PropertyFilter;
import org.ezplatform.core.service.BaseService;
import org.ezplatform.office.meeting.common.util.MeetingSendMsgUtils;
import org.ezplatform.office.meeting.info.dao.ApplyRecordDao;
import org.ezplatform.office.meeting.info.entity.ApplyRecord;
import org.ezplatform.office.meeting.info.entity.MeetingScope;
import org.ezplatform.office.meeting.info.service.MeetingScopeService;
import org.ezplatform.office.meeting.task.dao.MeetingTaskInfoDao;
import org.ezplatform.office.meeting.task.entity.MeetingTaskInfo;
import org.ezplatform.util.DateUtils;
import org.ezplatform.util.SqlUtils;
import org.ezplatform.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class MeetingTaskInfoService extends BaseService<MeetingTaskInfo, String>{
	
	@Autowired
	private MeetingTaskInfoDao meetingTaskInfoDao;
	
	@Autowired
	private ApplyRecordDao applyRecordDao;
	
	@Autowired
	private MeetingScopeService meetingScopeService;
	
	@Autowired
	private MeetingSendMsgUtils meetingSendMsgUtils;
	
    @Autowired
    private UserApiService userApiService;
	
	@Override
	protected JpaBaseDao<MeetingTaskInfo, String> getEntityDao() {
		return meetingTaskInfoDao;
	}
	
	/**
	 * PC端根据会议ID获取任务
	 * @param pageable
	 * @param buildFilters
	 * @param applyrecordId
	 * @param endTime
	 * @param corpId
	 * @return
	 */
	public Page<Map> findTaskInfoByPage(Pageable pageable, List<PropertyFilter> buildFilters,String applyrecordId,String endTime,String corpId, String userName){
		Map<String, Object> paramMap = new HashMap<String, Object>();
		StringBuffer sqlStr = new StringBuffer();
		sqlStr.append("select task.id,task.title,task.apply_record_id,task.end_time,task.progress,task.createdDate,task.response_user ");
		sqlStr.append("from oa_meeting_task_info task ");
		sqlStr.append("where task.apply_record_id = :applyrecordId and task.corp_id = :corpId ");
		paramMap.put("applyrecordId", applyrecordId);
		paramMap.put("corpId", corpId);

		if(!"".equals(endTime)){
			paramMap.put("startTime", DateUtils.parseTime(endTime + " 00:00:00"));
			paramMap.put("endTime", DateUtils.parseTime(endTime + " 23:59:59"));
			sqlStr.append("and task.end_time >= :startTime and task.end_time <= :endTime ");
		}

		if(StringUtils.isNotBlank(userName)){
			paramMap.put("userName", "%"+userName+"%");
			sqlStr.append("and EXISTS (SELECT oms.fieldDataValue from oa_meeting_apply_record_scope oms ");
			sqlStr.append("LEFT JOIN sys_user su ON oms.scopeValue = su.id ");
			sqlStr.append("where oms.fieldDataValue = task.response_user and su.user_name like :userName ) ");
		}
		String strSql = "";
		Sort sort = pageable.getSort();
		if(sort != null) {
			Order order = sort.getOrderFor("response_user_name");
			if(order != null) {
				String s = order.toString();
				if(s.contains("ASC")) {
					strSql = sqlStr.append(" order by task.response_user asc").toString();
				}else {
					strSql = sqlStr.append(" order by task.response_user desc").toString();
				}
			}else {
				strSql = PropertyFilter.getSqlByFilterAndPageable("task", sqlStr.toString(), "task.end_time,task.createdDate desc", buildFilters, pageable);
			}
		}else {
			strSql = PropertyFilter.getSqlByFilterAndPageable("task", sqlStr.toString(), null, buildFilters, pageable);
		}
		Page<Map> page = super.findByPageNativeSQL(pageable, strSql, paramMap);

		List<Map> list = page.getContent();
		List<String> responseIds = new ArrayList<>();
		if(list!=null && list.size()>0){
			for (Map map: list) {
				responseIds.add(StringUtils.null2String(map.get("response_user")));
			}
		}
		if(responseIds!=null && responseIds.size()>0){
			StringBuffer sql = new StringBuffer();
			Map<String, Object> params = new HashMap<>();
			params.put("corpId", corpId);
			params.put("responseIds", responseIds);
			sql.append("select su.id, su.user_name,oms.fieldDataValue from oa_meeting_apply_record_scope oms ");
			sql.append("left join sys_user su on oms.scopeValue = su.id and su.corp_id = :corpId  ");
			sql.append("where oms.fieldDataValue in (:responseIds) ");
			sql.append("order by oms.fieldDataValue, oms.sort_no ");

			List<Map> response = super.findByListNativeQuery(sql.toString(), "", params);
			String responseId = "", fieldDataValue = "";
			for (int i=0; i<list.size(); i++) {
				Map task = list.get(i);
				responseId = StringUtils.null2String(task.get("response_user"));
				String response_user_name = "",  user_id = "";
				for(int j=0; j<response.size(); j++){
					Map map = response.get(j);
					fieldDataValue = StringUtils.null2String(map.get("fieldDataValue"));
					if(fieldDataValue.equals(responseId)){
						response_user_name += StringUtils.null2String(map.get("user_name")) + ",";
						user_id += StringUtils.null2String(map.get("id")) + ",";
					}
				}
				if(!response_user_name.equals("")){
					response_user_name = response_user_name.substring(0, response_user_name.length()-1);
				}
				if(!user_id.equals("")){
					user_id = user_id.substring(0, user_id.length()-1);
				}
				task.put("response_user_name", response_user_name);
				task.put("user_id", user_id);
			}
		}
		
		return page;
	}
	
	/**
	 * 移动端获取任务列表
	 * @param status
	 * @param page
	 * @param pageSize
	 * @param applyrecordId
	 * @param corpId
	 * @return
	 */
	public List<Map> findTaskInfoByPage(String status, String page, String pageSize, String applyrecordId,String userId,String corpId, String title){
		List<Map> list = new ArrayList<>();
		StringBuffer sqlStr = new StringBuffer();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("corpId", corpId);
		sqlStr.append("select task.id,task.title,task.apply_record_id applyRecordId,task.end_time endtime,task.progress,");
		sqlStr.append("task.createdDate,task.response_user response ");
		sqlStr.append("from oa_meeting_task_info task ");
		if(StringUtils.isNotBlank(applyrecordId)){
			sqlStr.append("where task.apply_record_id = :applyrecordId and task.corp_id = :corpId ");
			paramMap.put("applyrecordId", applyrecordId);
		}else if(StringUtils.isNotBlank(userId)){
			sqlStr.append("LEFT JOIN oa_meeting_apply_record_scope oms1 ON task.response_user = oms1.fieldDataValue ");
			sqlStr.append("where oms1.scopeValue = :userId and oms1.fieldData = 'response_user' and task.corp_id = :corpId ");
			paramMap.put("userId", userId);
		}
		
		if(StringUtils.isNotBlank(status)){
			if(StringUtils.equals("2", status)){
				sqlStr.append("and task.progress = '100' ");
			}else{
				if(StringUtils.equals("0", status)){//已到期
					sqlStr.append("and task.end_time < :searchTime and task.progress < 100 ");
					String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
					paramMap.put("searchTime", DateUtils.parseDate(searchTime));
				}else if(StringUtils.equals("1", status)){//进行中
					sqlStr.append("and task.end_time >= :searchTime and task.progress < 100 ");
					String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
					paramMap.put("searchTime", DateUtils.parseDate(searchTime));
				}else{//0,1 已到期或进行中
					sqlStr.append("and task.progress < 100 ");
				}
			}
		}
		
		if(StringUtils.isNotBlank(title)){
			sqlStr.append("and task.title like :title ");
			paramMap.put("title", "%"+title+"%");
		}
		sqlStr.append("order by task.end_time,task.createdDate desc ");

		int size = 0;
		int no = 0;
		if (StringUtils.isNotBlank(pageSize)) {
			size = Integer.valueOf(pageSize);
		}
		if (StringUtils.isNotBlank(page)) {
			no = Integer.valueOf(page);
		}
		int start = (no - 1) * size;
		list = super.findByListNativeQuery(sqlStr.toString(), "", paramMap, start, size);
		List<String> responseIds = new ArrayList<>();
		if(list!=null && list.size()>0){
			for (Map map: list) {
				responseIds.add(StringUtils.null2String(map.get("response")));
			}
		}
		if(responseIds!=null && responseIds.size()>0){
			StringBuffer sql = new StringBuffer();
			Map<String, Object> params = new HashMap<>();
			params.put("corpId", corpId);
			params.put("responseIds", responseIds);
			sql.append("select su.id, su.user_name,oms.fieldDataValue as value from oa_meeting_apply_record_scope oms ");
			sql.append("left join sys_user su on oms.scopeValue = su.id and su.corp_id = :corpId  ");
			sql.append("where oms.fieldDataValue in (:responseIds) ");
			sql.append("order by oms.fieldDataValue, oms.sort_no ");

			List<Map> response = super.findByListNativeQuery(sql.toString(), "", params);
			String responseId = "", fieldDataValue = "";
			for (int i=0; i<list.size(); i++) {
				Map task = list.get(i);
				responseId = StringUtils.null2String(task.get("response"));
				String resUserName = "";
				for(int j=0; j<response.size(); j++){
					Map map = response.get(j);
					fieldDataValue = StringUtils.null2String(map.get("value"));
					if(fieldDataValue.equals(responseId)){
						resUserName += StringUtils.null2String(map.get("user_name")) + ",";
					}
				}
				if(!resUserName.equals("")){
					resUserName = resUserName.substring(0, resUserName.length()-1);
				}
				task.put("resUserName", resUserName);
			}
		}
		return list;
	}
	
	/**
	 * PC端获取当前登录人负责的会议任务
	 * @param pageable
	 * @param buildFilters
	 * @param userId
	 * @param corpId
	 * @param status
	 * @param endTime
	 * @return
	 */
	public Page<Map> findMineTasksByPage(Pageable pageable, List<PropertyFilter> buildFilters,String userId,String corpId,String status, String meetingName, String startTime, String endTime){
		Map<String, Object> paramMap = new HashMap<String, Object>();
		StringBuffer sqlStr = new StringBuffer();
		sqlStr.append("select id,title,apply_record_id,end_time,progress,response_user,name,createdDate from (");
		sqlStr.append("select task.id,task.title,task.apply_record_id,task.end_time,task.progress,task.createdDate,");
		sqlStr.append("task.response_user,apply.name from (");
		
		sqlStr.append("select task.id,task.title,task.apply_record_id,task.end_time,task.progress,task.createdDate,");
		sqlStr.append("task.response_user from oa_meeting_task_info task where task.corp_id = :corpId ");
		if(!"".equals(status)){
			if("2".equals(status)){
				sqlStr.append("and task.progress = '100' ");
			}else{
				String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
				paramMap.put("searchTime", DateUtils.parseTime(searchTime + " 00:00:00"));
				if("0".equals(status)){//已到期
					sqlStr.append("and task.end_time < :searchTime and task.progress < 100 ");
				}else if("1".equals(status)){//进行中
					sqlStr.append("and task.end_time >= :searchTime and task.progress < 100 ");
				}
			}
		}
		if(StringUtils.isNotBlank(startTime)){
			paramMap.put("startTime", startTime);
			sqlStr.append(" and task.end_time >= :startTime");
		}
		if(StringUtils.isNotBlank(endTime)){
			paramMap.put("endTime", endTime);
			sqlStr.append(" and task.end_time <= :endTime ");
		}
		sqlStr.append(") task ");
		
		sqlStr.append("LEFT JOIN oa_meeting_apply_record_scope oms ON task.response_user = oms.fieldDataValue ");
		sqlStr.append("LEFT JOIN oa_meeting_apply_record apply ON task.apply_record_id = apply.id ");
		sqlStr.append("where oms.scopeValue = :userId ");
		
		paramMap.put("userId", userId);
		paramMap.put("corpId", corpId);
		
		
		if(StringUtils.isNotBlank(meetingName)){
			paramMap.put("meetingName", "%" + meetingName + "%");
			sqlStr.append(" and apply.name like :meetingName");
		}
		
		sqlStr.append(") t1 where 1=1 ");
		
		String strSql = PropertyFilter.getSqlByFilterAndPageable("t1", sqlStr.toString(), "t1.end_time,t1.createdDate desc", buildFilters, pageable);
		Page<Map> page = super.findByPageNativeSQL(pageable, strSql, paramMap);
		return page;
	}
	
	/**
	 * 根据不同条件统计任务数量
	 * @param status
	 * @param applyRecordId
	 * @param userId
	 * @param corpId
	 * @return
	 */
	public int taskInfosCount(String status, String applyRecordId, String userId,String corpId,String title){
		Map<String, Object> paramMap = new HashMap<String, Object>();
	    paramMap.put("corpId", corpId);
		StringBuffer sqlStr = new StringBuffer();
		sqlStr.append("select count(task.id) from oa_meeting_task_info task ");
		if(!"".equals(applyRecordId)){
			paramMap.put("applyRecordId", applyRecordId);
			sqlStr.append("where task.apply_record_id =:applyRecordId and task.corp_id =:corpId ");
		}else if(!"".equals(userId)){
			paramMap.put("userId", userId);
			sqlStr.append("LEFT JOIN oa_meeting_apply_record_scope oms ON task.response_user = oms.fieldDataValue ");
			sqlStr.append("where oms.scopeValue =:userId and task.corp_id =:corpId ");
		}
		
		if("0".equals(status)){//已到期
			String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
			paramMap.put("searchTime", DateUtils.parseDate(searchTime));
			sqlStr.append("and task.end_time <:searchTime and task.progress < 100 ");
		}else if("1".equals(status)){//进行中
			String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
			paramMap.put("searchTime", DateUtils.parseDate(searchTime));
			sqlStr.append("and task.end_time >=:searchTime and task.progress < 100 ");
		}else if("2".equals(status)){
			sqlStr.append("and task.progress = 100 ");
		}else{
			sqlStr.append("and task.progress < 100 ");
		}
		
		if(!"".equals(title)){
			paramMap.put("title", "%"+title+"%");
			sqlStr.append("and task.title like :title ");
		}
		
		Query query = super.getEntityManager().createNativeQuery(sqlStr.toString());
		SqlUtils.setQueryParameter(paramMap, query);
		int count = Integer.parseInt(query.getSingleResult().toString());
		return count;
	}
	
	/**
	 * 根据会议任务标题和会议id查找任务
	 * @param applyRecordId
	 * @param title
	 * @return
	 */
	public MeetingTaskInfo findTaskByTitle(String applyRecordId, String title){
		return this.meetingTaskInfoDao.findTaskInfo(applyRecordId, title);
	}
	
	/**
	 * 修改任务进度
	 * @param progress
	 * @param ids
	 * @return
	 */
	public int updateProgress(int progress, String... ids){
		return this.meetingTaskInfoDao.updateProgress(progress, ids);
	}
	
	/**
	 * 修改任务完成情况
	 * @param progress
	 * @param ids
	 * @return
	 */
	public int updateDetails(String comDetails, String id){
		return this.meetingTaskInfoDao.updateDetails(comDetails, id);
	}
	
	/**
	 * 删除任务
	 * @param id
	 * @return
	 */
	public int deleteTask(String id){
		return this.meetingTaskInfoDao.deleteTask(id);
	}
	
	/**
	 * 根据会议id删除任务
	 * @param id
	 * @return
	 */
	public int deleteByRecordId(String... applyRecordId){
		return this.meetingTaskInfoDao.deleteByRecordId(applyRecordId);
	}
	
	/**
	 * 根据会议id查询任务id
	 * @param applyRecordId
	 * @return
	 */
	public List<String> findTaskInfoIdsByApplyRecordIds(String applyRecordId){
		return this.meetingTaskInfoDao.findTaskInfoIdsByApplyRecordIds(applyRecordId);
	}
	
	/**
	 * 定时发送会议任务到期提醒
	 * @param request
	 */
	public void remindTaskInfoJob(HttpServletRequest request){
		String searchTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
		List<MeetingTaskInfo> taskInfos = this.meetingTaskInfoDao.findTaskInfo(DateUtils.parseTime(searchTime + " 00:00:00"));
		if(!taskInfos.isEmpty() && taskInfos.size()>0){
			for (MeetingTaskInfo taskInfo : taskInfos) {
				Date endTime = taskInfo.getEndTime();
				int remindTime = taskInfo.getRemindTime();
				Date date = DateUtils.addDays(endTime, -remindTime);
				String dateStr = DateUtils.formatDate(date);
				if(searchTime.equals(dateStr)){
					String remindType = StringUtils.null2String(taskInfo.getRemindType());
					if(remindType.indexOf("2") >= 0){
						String corpId = taskInfo.getCorpId();
                    	ApplyRecord applyRecord = this.applyRecordDao.findById(taskInfo.getApplyRecordId()).get();
            			if(applyRecord != null){
            				Map<String, Object> ds = new HashMap<>();
            				ds.put("type", "7");
            				ds.put("applyRecordId", applyRecord.getId());
                			ds.put("meetingName", applyRecord.getName());
                			ds.put("endTime", DateUtils.formatDate(endTime,"yyyy年MM月dd日"));
                			ds.put("title", taskInfo.getTitle());
                			ds.put("id", taskInfo.getId());
                			String noticeUserId = taskInfo.getCreatedBy();
                			ds.put("userId", noticeUserId);
                			String token = JwtUtils.resolveToken(request);
                			String noticeUserName = "";
                			if(StringUtils.isNoneEmpty(noticeUserId)) {
                				Map<String, Object> userMap = userApiService.getUser(noticeUserId, corpId, "", token);
                				if(MapUtils.isNotEmpty(userMap)) {
                					noticeUserName = StringUtils.null2String(userMap.get("userName"));
                				}
                			}
                			ds.put("userName", noticeUserName);
                			ds.put("userOrg", taskInfo.getCreatedOrg());
                			
                			ds.put("boardroom", StringUtils.isNotEmpty(applyRecord.getAddress()) ? applyRecord.getAddress():"无");
                			
							Map<String, String> idsMap = new HashMap<>();
							idsMap = this.getUserThirdIds(taskInfo.getResponseUser());
							String ids = idsMap.get("ids");
                			if(!StringUtils.isEmpty(ids)){
                				boolean mobilePush = false;
    				            boolean emailPush = false;
    				            boolean smsPublish = false;
    							String mesgPush = applyRecord.getMessagePush();
    							if(StringUtils.isNotBlank(mesgPush) && mesgPush.contains("mobile")) mobilePush = true;
    							if(StringUtils.isNotBlank(mesgPush) && mesgPush.contains("email")) emailPush = true;
    							if(StringUtils.isNotBlank(mesgPush) && mesgPush.contains("sms")) smsPublish = true;
                				ds.put("userIds", ids);
                				ds.put("orgIds", "");
                				this.meetingSendMsgUtils.sendMail(ds, emailPush, corpId, token);
                				this.meetingSendMsgUtils.sendMsgToApp(ds, mobilePush, corpId, token, request);
            					this.meetingSendMsgUtils.sendSMS(ds, smsPublish, corpId, token);
                			}
                			String jsonIds = idsMap.get("jsonIds");
                			if(StringUtils.isNotBlank(jsonIds) && !"[]".equals(jsonIds)){
                				this.meetingSendMsgUtils.sendMessage(ds, jsonIds, corpId, token);
							}
            			}
					}
				}
			}
		}
	}
	
	public Map<String, String> getUserThirdIds(String user){
		Map<String, String> idsMap = new HashMap<>();
//    	List<String> userIds = new ArrayList<>();
        //负责人
    	String ids = "";
		String jsonIds = "[";
        List<String> aScopeList = new ArrayList<>();
        aScopeList.add(user);
        List<MeetingScope> userList = this.meetingScopeService.getMeetingScopeList("oa_meeting_task_info", "response_user", aScopeList,true);
        if(userList != null && userList.size()>0){
        	for (MeetingScope scope : userList) {
//        		userIds.add(scope.getScopevalue());
				jsonIds +="{\"10\":\""+scope.getScopevalue()+"\"},";
				ids += scope.getScopevalue() + ",";
			}
        }
        
//        StringBuffer sql = new StringBuffer();
//        sql.append("select dd_uid from sys_user where id in (?1) ");
//        List<Object> result = super.getEntityManager().createNativeQuery(sql.toString()).setParameter(1, userIds).getResultList();
//		if(result != null){
//			for (Object id : result) {
//				if(id != null){
//					ids += id + ",";
//				}
//			}
//		}
        if(!StringUtils.isEmpty(ids)){
			ids = ids.substring(0, ids.length()-1);
		}
		idsMap.put("ids", ids);
		if(StringUtils.isNotBlank(jsonIds)){
			jsonIds = jsonIds.substring(0, jsonIds.length()-1);
		}
		idsMap.put("jsonIds", jsonIds + "]");
		return idsMap;
    }
	
}
